package tools

import (
	"encoding/json"
	"gitee.com/dennis-kk/service-box-go/util/errors"
	"io/ioutil"
	"math/rand"
	"net"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"sync"
)

var (
	internalIPOnce sync.Once
	internalIP     = ""
)

//IsNotNil 判断是否nil
func IsNotNil(object interface{}) bool {
	return !IsNilObject(object)
}

//IsNilObject 判断是否空对象
func IsNilObject(object interface{}) bool {
	if object == nil {
		return true
	}

	value := reflect.ValueOf(object)
	kind := value.Kind()
	if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
		return true
	}

	return false
}

func ParseIp(addrWithPort string) (string, error) {
	pair := strings.Split(addrWithPort, ":")
	if len(pair) < 2 {
		return "", errors.HostIpError
	}

	switch pair[0] {
	case "localhost":
		addrWithPort = "127.0.0.1:" + pair[1]
	case "hostname":
		// 支持从hostname 获取真正的ip和端口
		host, err := os.Hostname()
		if err != nil {
			return "", err
		}
		addrs, err := net.LookupHost(host)
		// 如果这里获取到多个配置，就随机一个
		addrWithPort = addrs[rand.Int()%len(addrs)] + ":" + pair[1]
	}
	return addrWithPort, nil
}

func IsEffectiveDir(path string) bool {
	//check file exist
	stat, err := os.Stat(path)
	if os.IsNotExist(err) {
		return false
	}
	//check is directory
	if !stat.IsDir() {
		return false
	}
	return true
}

// IsRegularFile 是否普通文档
func IsRegularFile(name string) bool {
	//check file exist
	stat, err := os.Stat(name)
	if os.IsNotExist(err) {
		return false
	}

	return stat.Mode().IsRegular()
}

func ListFileInDirWithSuffix(root string, suffix string) ([]string, error) {
	var files []string
	walk := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}

		fileSuffix := filepath.Ext(path)
		if fileSuffix != suffix {
			return nil
		}

		files = append(files, path)
		return nil
	}

	err := filepath.Walk(root, walk)
	if err != nil {
		return nil, err
	}

	return files, nil
}

//JsonFileUnmarshalHelper 打开文件并且序列化到结构体, 方便关闭文件
func JsonFileUnmarshalHelper(file string, desc interface{}) (err error) {
	fh, err := os.Open(file)
	if err != nil {
		return err
	}

	defer func() {
		if r := recover(); r != nil {
		}
		_ = fh.Close()
	}()

	fBuffer, err := ioutil.ReadAll(fh)
	if err != nil {
		return err
	}

	err = json.Unmarshal(fBuffer, desc)
	if err != nil {
		return err
	}
	return nil
}
